#pragma once

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <functional>

#include "log.hpp"
#include "inetaddr.hpp"

using namespace mylog;
using namespace myaddr;

// using func_t = std::function<std::string(const std::string &)>;
using func_t = std::function<std::string(const std::string &, const Addr &)>;
namespace udpserver
{
    const static int default_fd = -1;
    class UdpServer
    {
    public:
        UdpServer(uint16_t port, func_t func)
            : _sockfd(default_fd), _port(port), _running(false), _func(func)
        {
        }
        ~UdpServer()
        {
        }
        void Init()
        {
            // 打开网络文件
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd < 0)
            {
                LOG(Level::FATAL) << "socket error";
                exit(1);
            }
            LOG(Level::INFO) << "socket success, _sockfd : " << _sockfd;
            // 绑定端口号
            struct sockaddr_in skd;
            bzero(&skd, sizeof(skd));    // 置0
            skd.sin_family = AF_INET;    // 网络通信
            skd.sin_port = htons(_port); // htons 本地转网络(字符序列)
            // inet_addr()  字符ip  -->  4字节ip  --> 网络序列
            skd.sin_addr.s_addr = INADDR_ANY;

            int n = bind(_sockfd, (struct sockaddr *)&skd, sizeof(skd));
            if (n < 0)
            {
                LOG(Level::FATAL) << "bind error";
                exit(2);
            }
            LOG(Level::INFO) << "bind success, _sockfd : " << _sockfd;
        }
        void Start()
        {
            _running = true;
            // 接受信息
            while (_running)
            {
                char buff[256];
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                // 接受信息
                ssize_t n = recvfrom(_sockfd, buff, sizeof(buff) - 1, 0, (struct sockaddr *)&peer, &len);
                buff[n] = '\0';
                // std::string reply = _func(buff); // 回调

                // 回复信息
                std::string reply = _func(buff, Addr(peer));
                ssize_t m = sendto(_sockfd, reply.c_str(), reply.size(), 0, (struct sockaddr *)&peer, sizeof(peer));
            }
        }

    private:
        int _sockfd;
        uint16_t _port; // 端口号
        bool _running;
        func_t _func;
    };
}

// namespace udpserver
// {
//     const static int default_fd = -1;
//     class UdpServer
//     {
//     public:
//         UdpServer(const std::string &addr, uint16_t port)
//             : _sockfd(-1), _addr(addr), _port(port), _running(false)
//         {
//         }
//         // UdpServer(uint16_t port)
//         //     : _sockfd(default_fd), _port(port), _running(false)
//         // {
//         // }
//         ~UdpServer()
//         {
//         }
//         void Init()
//         {
//             // 打开网络文件
//             _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
//             if (_sockfd < 0)
//             {
//                 LOG(Level::FATAL) << "socket error";
//                 exit(1);
//             }
//             LOG(Level::INFO) << "socket success, _sockfd : " << _sockfd;
//             // 绑定端口号
//             struct sockaddr_in skd;
//             bzero(&skd, sizeof(skd));    // 置0
//             skd.sin_family = AF_INET;    // 网络通信
//             skd.sin_port = htons(_port); // htons 本地转网络(字符序列)
//             // inet_addr()  字符ip  -->  4字节ip  --> 网络序列
//             skd.sin_addr.s_addr = inet_addr(_addr.c_str());
//             // skd.sin_addr.s_addr = htons(INADDR_ANY);

//             std::cout << "_port : " << _port << ", sin_port : " << skd.sin_port << std::endl;

//             int n = bind(_sockfd, (struct sockaddr *)&skd, sizeof(skd));
//             if (n < 0)
//             {
//                 LOG(Level::FATAL) << "bind error";
//                 exit(2);
//             }
//             LOG(Level::INFO) << "bind success, _sockfd : " << _sockfd;
//         }
//         void Start()
//         {
//             _running = true;
//             // 接受信息
//             while (_running)
//             {
//                 char buff[256];
//                 struct sockaddr_in src;
//                 socklen_t len = sizeof(src);
//                 // 接受信息
//                 ssize_t n = recvfrom(_sockfd, buff, sizeof(buff) - 1, 0, (struct sockaddr *)&src, &len);
//                 if (n < 0)
//                 {
//                     LOG(Level::ERROR) << " recvfrom error ";
//                     exit(3);
//                 }
//                 buff[n] = '\0';
//                 std::string reply = "server say@ ";
//                 reply += buff;
//                 ssize_t m = sendto(_sockfd, reply.c_str(), reply.size(), 0, (struct sockaddr *)&src, sizeof(src));
//                 if (m < 0)
//                 {
//                     LOG(Level::ERROR) << " sendto error ";
//                     exit(4);
//                 }
//             }
//         }

//     private:
//         int _sockfd;
//         uint16_t _port; // 端口号
//         std::string _addr; // ip
//         bool _running;
//     };
// }